home *** CD-ROM | disk | FTP | other *** search
/ Micromanía 92 / CDMM92_1.ISO / SOF 2 SDK / sof2sdk-101.msi / _92D6AC311BB48EBA344BBABC89DA6AB0 / _BCB2495716C748D3852ECC84A0611EE6 < prev    next >
Encoding:
Text File  |  2002-06-05  |  16.0 KB  |  596 lines

  1. // Copyright (C) 2001-2002 Raven Software.
  2. //
  3. // g_misc.c
  4.  
  5. #include "g_local.h"
  6.  
  7.  
  8. /*QUAKED func_group (0 0 0) ?
  9. Used to group brushes together just for editor convenience.  They are turned into normal brushes by the utilities.
  10. */
  11.  
  12. /*QUAKED info_notnull (0 0.5 0) (-4 -4 -4) (4 4 4)
  13. Used as a positional target for in-game calculation, like jumppad targets.
  14. target_position does the same thing
  15. */
  16. void SP_info_notnull( gentity_t *self )
  17. {
  18.     G_SetOrigin( self, self->s.origin );
  19. }
  20.  
  21. /*
  22. =================================================================================
  23. TeleportPlayer
  24. =================================================================================
  25. */
  26. void TeleportPlayer ( gentity_t *player, vec3_t origin, vec3_t angles ) 
  27. {
  28.     gentity_t    *tent;
  29.  
  30.     // use temp events at source and destination to prevent the effect
  31.     // from getting dropped by a second player event
  32.     if ( !G_IsClientSpectating ( player->client ) ) 
  33.     {
  34.         tent = G_TempEntity( player->client->ps.origin, EV_PLAYER_TELEPORT_OUT );
  35.         tent->s.clientNum = player->s.clientNum;
  36.  
  37.         tent = G_TempEntity( origin, EV_PLAYER_TELEPORT_IN );
  38.         tent->s.clientNum = player->s.clientNum;
  39.     }
  40.  
  41.     // unlink to make sure it can't possibly interfere with G_KillBox
  42.     trap_UnlinkEntity (player);
  43.  
  44.     VectorCopy ( origin, player->client->ps.origin );
  45.     player->client->ps.origin[2] += 1;
  46.  
  47.     // spit the player out
  48.     AngleVectors( angles, player->client->ps.velocity, NULL, NULL );
  49.     VectorScale( player->client->ps.velocity, 400, player->client->ps.velocity );
  50.     player->client->ps.pm_time = 160;        // hold time
  51.     player->client->ps.pm_flags |= PMF_TIME_KNOCKBACK;
  52.  
  53.     // toggle the teleport bit so the client knows to not lerp
  54.     player->client->ps.eFlags ^= EF_TELEPORT_BIT;
  55.  
  56.     // set angles
  57.     SetClientViewAngle( player, angles );
  58.  
  59.     // kill anything at the destination
  60.     if ( !G_IsClientSpectating ( player->client ) ) 
  61.     {
  62.         G_KillBox (player);
  63.     }
  64.  
  65.     // save results of pmove
  66.     BG_PlayerStateToEntityState( &player->client->ps, &player->s, qtrue );
  67.  
  68.     // use the precise origin for linking
  69.     VectorCopy( player->client->ps.origin, player->r.currentOrigin );
  70.  
  71.     if ( !G_IsClientSpectating ( player->client ) ) 
  72.     {
  73.         trap_LinkEntity (player);
  74.     }
  75. }
  76.  
  77.  
  78. /*QUAKED misc_teleporter_dest (1 0 0) (-32 -32 -24) (32 32 -16)
  79. Point teleporters at these.
  80. Now that we don't have teleport destination pads, this is just
  81. an info_notnull
  82. */
  83. void SP_misc_teleporter_dest( gentity_t *ent ) 
  84. {
  85. }
  86.  
  87. //===========================================================
  88.  
  89. /*QUAKED misc_model (1 0 0) (-16 -16 -16) (16 16 16) RMG
  90. this model is inserted into the bsp file
  91. "model"        arbitrary .md3 file to display
  92. */
  93. void SP_misc_model( gentity_t *ent ) 
  94. {
  95. #if 0
  96.     ent->s.modelindex = G_ModelIndex( ent->model );
  97.     VectorSet (ent->mins, -16, -16, -16);
  98.     VectorSet (ent->maxs, 16, 16, 16);
  99.     trap_LinkEntity (ent);
  100.  
  101.     G_SetOrigin( ent, ent->s.origin );
  102.     VectorCopy( ent->s.angles, ent->s.apos.trBase );
  103. #else
  104.     G_FreeEntity( ent );
  105. #endif
  106. }
  107.  
  108.  
  109. /*QUAKED misc_G2model (1 0 0) (-16 -16 -16) (16 16 16)
  110. "model"        arbitrary .glm file to display
  111. */
  112. void SP_misc_G2model( gentity_t *ent ) {
  113.  
  114. #if 0
  115.     char name1[200] = "models/players/kyle/modelmp.glm";
  116.     trap_G2API_InitGhoul2Model(&ent->s, name1, G_ModelIndex( name1 ), 0, 0, 0, 0);
  117.     trap_G2API_SetBoneAnim(ent->s.ghoul2, 0, "model_root", 0, 12, BONE_ANIM_OVERRIDE_LOOP, 1.0f, level.time, -1, -1);
  118.     ent->s.radius = 150;
  119. //    VectorSet (ent->mins, -16, -16, -16);
  120. //    VectorSet (ent->maxs, 16, 16, 16);
  121.     trap_LinkEntity (ent);
  122.  
  123.     G_SetOrigin( ent, ent->s.origin );
  124.     VectorCopy( ent->s.angles, ent->s.apos.trBase );
  125. #else
  126.     G_FreeEntity( ent );
  127. #endif
  128. }
  129.  
  130. //===========================================================
  131.  
  132. void locateCamera( gentity_t *ent ) 
  133. {
  134.     vec3_t        dir;
  135.     gentity_t    *target;
  136.     gentity_t    *owner;
  137.  
  138.     owner = G_PickTarget( ent->target );
  139.     if ( !owner ) 
  140.     {
  141.         Com_Printf( "Couldn't find target for misc_partal_surface\n" );
  142.         G_FreeEntity( ent );
  143.         return;
  144.     }
  145.     ent->r.ownerNum = owner->s.number;
  146.  
  147.     // frame holds the rotate speed
  148.     if ( owner->spawnflags & 1 ) 
  149.     {
  150.         ent->s.frame = 25;
  151.     } 
  152.     else if ( owner->spawnflags & 2 ) 
  153.     {
  154.         ent->s.frame = 75;
  155.     }
  156.  
  157.     // swing camera ?
  158.     if ( owner->spawnflags & 4 ) 
  159.     {
  160.         // set to 0 for no rotation at all
  161.         ent->s.gametypeitems = 0;
  162.     }
  163.     else 
  164.     {
  165.         ent->s.gametypeitems = 1;
  166.     }
  167.  
  168.     // clientNum holds the rotate offset
  169.     ent->s.clientNum = owner->s.clientNum;
  170.  
  171.     VectorCopy( owner->s.origin, ent->s.origin2 );
  172.  
  173.     // see if the portal_camera has a target
  174.     target = G_PickTarget( owner->target );
  175.     if ( target ) {
  176.         VectorSubtract( target->s.origin, owner->s.origin, dir );
  177.         VectorNormalize( dir );
  178.     } else {
  179.         G_SetMovedir( owner->s.angles, dir );
  180.     }
  181.  
  182.     ent->s.eventParm = DirToByte( dir );
  183. }
  184.  
  185. /*QUAKED misc_portal_surface (0 0 1) (-8 -8 -8) (8 8 8)
  186. The portal surface nearest this entity will show a view from the targeted misc_portal_camera, or a mirror view if untargeted.
  187. This must be within 64 world units of the surface!
  188. */
  189. void SP_misc_portal_surface(gentity_t *ent) 
  190. {
  191.     VectorClear( ent->r.mins );
  192.     VectorClear( ent->r.maxs );
  193.     trap_LinkEntity (ent);
  194.  
  195.     ent->r.svFlags = SVF_PORTAL;
  196.     ent->s.eType = ET_PORTAL;
  197.  
  198.     if ( !ent->target ) 
  199.     {
  200.         VectorCopy( ent->s.origin, ent->s.origin2 );
  201.     } 
  202.     else 
  203.     {
  204.         ent->think = locateCamera;
  205.         ent->nextthink = level.time + 100;
  206.     }
  207. }
  208.  
  209. /*QUAKED misc_portal_camera (0 0 1) (-8 -8 -8) (8 8 8) slowrotate fastrotate noswing
  210. The target for a misc_portal_director.  You can set either angles or target another entity to determine the direction of view.
  211. "roll" an angle modifier to orient the camera around the target vector;
  212. */
  213. void SP_misc_portal_camera(gentity_t *ent) 
  214. {
  215.     float    roll;
  216.  
  217.     VectorClear( ent->r.mins );
  218.     VectorClear( ent->r.maxs );
  219.     trap_LinkEntity (ent);
  220.  
  221.     G_SpawnFloat( "roll", "0", &roll );
  222.  
  223.     ent->s.clientNum = roll/360.0 * 256;
  224. }
  225.  
  226. /*QUAKED misc_bsp (1 0 0) (-16 -16 -16) (16 16 16)
  227. "bspmodel"        arbitrary .bsp file to display
  228. */
  229. void SP_misc_bsp(gentity_t *ent) 
  230. {
  231.     char    temp[MAX_QPATH];
  232.     char    *out;
  233.     float    newAngle;
  234.     int        tempint;
  235.  
  236.     G_SpawnFloat( "angle", "0", &newAngle );
  237.     if (newAngle != 0.0)
  238.     {
  239.         ent->s.angles[1] = newAngle;
  240.     }
  241.     // don't support rotation any other way
  242.     ent->s.angles[0] = 0.0;
  243.     ent->s.angles[2] = 0.0;
  244.     
  245.     G_SpawnString("bspmodel", "", &out);
  246.  
  247.     ent->s.eFlags = EF_PERMANENT;
  248.  
  249.     // Mainly for debugging
  250.     G_SpawnInt( "spacing", "0", &tempint);
  251.     ent->s.time2 = tempint;
  252.     G_SpawnInt( "flatten", "0", &tempint);
  253.     ent->s.time = tempint;
  254.  
  255.     Com_sprintf(temp, MAX_QPATH, "#%s", out);
  256.     trap_SetBrushModel( ent, temp );  // SV_SetBrushModel -- sets mins and maxs
  257.     G_BSPIndex(temp);
  258.  
  259.     level.mNumBSPInstances++;
  260.     Com_sprintf(temp, MAX_QPATH, "%d-", level.mNumBSPInstances);
  261.     VectorCopy(ent->s.origin, level.mOriginAdjust);
  262.     level.mRotationAdjust = ent->s.angles[1];
  263.     level.mTargetAdjust = temp;
  264.     level.hasBspInstances = qtrue;
  265.     level.mBSPInstanceDepth++;
  266.     G_SpawnString("filter", "", &out);
  267.     strcpy(level.mFilter, out);
  268.     G_SpawnString("teamfilter", "", &out);
  269.     strcpy(level.mTeamFilter, out);
  270.  
  271.     VectorCopy( ent->s.origin, ent->s.pos.trBase );
  272.     VectorCopy( ent->s.origin, ent->r.currentOrigin );
  273.     VectorCopy( ent->s.angles, ent->s.apos.trBase );
  274.     VectorCopy( ent->s.angles, ent->r.currentAngles );
  275.  
  276.     ent->s.eType = ET_MOVER;
  277.  
  278.     trap_LinkEntity (ent);
  279.  
  280.     trap_SetActiveSubBSP(ent->s.modelindex);
  281.     G_SpawnEntitiesFromString(qtrue);
  282.     trap_SetActiveSubBSP(-1);
  283.  
  284.     level.mBSPInstanceDepth--;
  285.     level.mFilter[0] = level.mTeamFilter[0] = 0;
  286.  
  287.     if ( g_debugRMG.integer )
  288.     {
  289.         G_SpawnDebugCylinder ( ent->s.origin, ent->s.time2, &g_entities[0], 2000, COLOR_WHITE );
  290.  
  291.         if ( ent->s.time )
  292.         {
  293.             G_SpawnDebugCylinder ( ent->s.origin, ent->s.time, &g_entities[0], 2000, COLOR_RED );
  294.         }
  295.     }
  296. }
  297.  
  298. /*QUAKED terrain (1.0 1.0 1.0) ?
  299. Terrain entity
  300. It will stretch to the full height of the brush
  301.  
  302. numPatches - integer number of patches to split the terrain brush into (default 200)
  303. terxels - integer number of terxels on a patch side (default 4) (2 <= count <= 8)
  304. seed - integer seed for random terrain generation (default 0)
  305. textureScale - float scale of texture (default 0.005)
  306. heightMap - name of heightmap data image to use
  307. terrainDef - defines how the game textures the terrain (file is base/ext_data/*.terrain - default is grassyhills)
  308. instanceDef - defines which bsp instances appear
  309. miscentDef - defines which client models spawn on the terrain (file is base/ext_data/*.miscents)
  310. densityMap - how dense the client models are packed
  311.  
  312. */
  313. void SP_terrain(gentity_t *ent) 
  314. {
  315.     char                temp[MAX_INFO_STRING];
  316.     char                final[MAX_QPATH];
  317.     char                seed[MAX_QPATH];
  318.     char                missionType[MAX_QPATH];
  319.     char                soundSet[MAX_QPATH];
  320.     int                    shaderNum, i;
  321.     char                *value;
  322.     int                    terrainID;
  323.  
  324.     VectorClear (ent->s.angles);
  325.     trap_SetBrushModel( ent, ent->model );
  326.  
  327.     // Get the shader from the top of the brush
  328. //    shaderNum = gi.CM_GetShaderNum(s.modelindex);
  329.     shaderNum = 0;
  330.  
  331.     if (RMG.integer)
  332.     {
  333.         // Grab the default terrain file from the RMG cvar
  334.         trap_Cvar_VariableStringBuffer("RMG_terrain", temp, MAX_QPATH);
  335.         Com_sprintf(final, MAX_QPATH, "%s", temp);
  336.         AddSpawnField("terrainDef", temp);
  337.  
  338.         trap_Cvar_VariableStringBuffer("RMG_instances", temp, MAX_QPATH);
  339.         Com_sprintf(final, MAX_QPATH, "%s", temp);
  340.         AddSpawnField("instanceDef", temp);
  341.  
  342.         trap_Cvar_VariableStringBuffer("RMG_miscents", temp, MAX_QPATH);
  343.         Com_sprintf(final, MAX_QPATH, "%s", temp);
  344.         AddSpawnField("miscentDef", temp);
  345.  
  346.         trap_Cvar_VariableStringBuffer("RMG_seed", seed, MAX_QPATH);
  347.         trap_Cvar_VariableStringBuffer("RMG_mission", missionType, MAX_QPATH);
  348.  
  349.         trap_Cvar_VariableStringBuffer("RMG_soundset", soundSet, MAX_QPATH);
  350.         trap_SetConfigstring(CS_AMBIENT_SOUNDSETS, soundSet );
  351.     }
  352.  
  353.     // Arbitrary (but sane) limits to the number of terxels
  354. //    if((mTerxels < MIN_TERXELS) || (mTerxels > MAX_TERXELS))
  355.     {
  356. //        Com_printf("G_Terrain: terxels out of range - defaulting to 4\n");
  357. //        mTerxels = 4;
  358.     }
  359.  
  360.     // Get info required for the common init
  361.     temp[0] = 0;
  362.     G_SpawnString("heightmap", "", &value);
  363.     Info_SetValueForKey(temp, "heightMap", value);
  364.  
  365.     G_SpawnString("numpatches", "400", &value);
  366.     Info_SetValueForKey(temp, "numPatches", va("%d", atoi(value)));
  367.  
  368.     G_SpawnString("terxels", "4", &value);
  369.     Info_SetValueForKey(temp, "terxels", va("%d", atoi(value)));
  370.  
  371.     Info_SetValueForKey(temp, "seed", seed);
  372.     Info_SetValueForKey(temp, "minx", va("%f", ent->r.mins[0]));
  373.     Info_SetValueForKey(temp, "miny", va("%f", ent->r.mins[1]));
  374.     Info_SetValueForKey(temp, "minz", va("%f", ent->r.mins[2]));
  375.     Info_SetValueForKey(temp, "maxx", va("%f", ent->r.maxs[0]));
  376.     Info_SetValueForKey(temp, "maxy", va("%f", ent->r.maxs[1]));
  377.     Info_SetValueForKey(temp, "maxz", va("%f", ent->r.maxs[2]));
  378.  
  379.     Info_SetValueForKey(temp, "modelIndex", va("%d", ent->s.modelindex));
  380.  
  381.     G_SpawnString("terraindef", "grassyhills", &value);
  382.     Info_SetValueForKey(temp, "terrainDef", value);
  383.  
  384.     G_SpawnString("instancedef", "", &value);
  385.     Info_SetValueForKey(temp, "instanceDef", value);
  386.  
  387.     G_SpawnString("miscentdef", "", &value);
  388.     Info_SetValueForKey(temp, "miscentDef", value);
  389.  
  390.     Info_SetValueForKey(temp, "missionType", missionType);
  391.     
  392.     for(i = 0; i < MAX_INSTANCE_TYPES; i++)
  393.     {
  394.         trap_Cvar_VariableStringBuffer(va("RMG_instance%d", i), final, MAX_QPATH);
  395.         if(strlen(final))
  396.         {
  397.             Info_SetValueForKey(temp, va("inst%d", i), final);
  398.         }
  399.     }
  400.  
  401.     // Set additional data required on the client only
  402.     G_SpawnString("densitymap", "", &value);
  403.     Info_SetValueForKey(temp, "densityMap", value);
  404.  
  405.     Info_SetValueForKey(temp, "shader", va("%d", shaderNum));
  406.     G_SpawnString("texturescale", "0.005", &value);
  407.     Info_SetValueForKey(temp, "texturescale", va("%f", atof(value)));
  408.  
  409.     // Initialise the common aspects of the terrain
  410.     terrainID = trap_CM_RegisterTerrain(temp);
  411. //    SetCommon(common);
  412.  
  413.     Info_SetValueForKey(temp, "terrainId", va("%d", terrainID));
  414.  
  415.     // Let the entity know if it is random generated or not
  416. //    SetIsRandom(common->GetIsRandom());
  417.  
  418.     // Let the game remember everything
  419.     level.landScapes[terrainID] = ent;
  420.  
  421.     // Send all the data down to the client
  422.     trap_SetConfigstring(CS_TERRAINS + terrainID, temp);
  423.  
  424.     // Make sure the contents are properly set
  425.     ent->r.contents = CONTENTS_TERRAIN;
  426.     ent->r.svFlags = SVF_NOCLIENT;
  427.     ent->s.eFlags = EF_PERMANENT;
  428.     ent->s.eType = ET_TERRAIN;
  429.  
  430.     // Hook into the world so physics will work
  431.     trap_LinkEntity(ent);
  432.  
  433.     // If running RMG then initialize the terrain and handle team skins
  434.     if ( RMG.integer ) 
  435.     {
  436.         trap_RMG_Init(terrainID);
  437.  
  438.         if ( level.gametypeData->teams )
  439.         {
  440.             char temp[MAX_QPATH];
  441.  
  442.             // Red team change from RMG ?
  443.             trap_GetConfigstring ( CS_GAMETYPE_REDTEAM, temp, MAX_QPATH );
  444.             if ( Q_stricmp ( temp, level.gametypeTeam[TEAM_RED] ) )
  445.             {
  446.                 level.gametypeTeam[TEAM_RED] = trap_VM_LocalStringAlloc ( temp );
  447.             }
  448.  
  449.             // Blue team change from RMG ?
  450.             trap_GetConfigstring ( CS_GAMETYPE_BLUETEAM, temp, MAX_QPATH );
  451.             if ( Q_stricmp ( temp, level.gametypeTeam[TEAM_BLUE] ) )
  452.             {
  453.                 level.gametypeTeam[TEAM_BLUE] = trap_VM_LocalStringAlloc ( temp );
  454.             }
  455.         }
  456.     }
  457. }
  458.  
  459. /*
  460. =================================================================================
  461. G_DebugCylinderThink
  462. =================================================================================
  463. */
  464. void G_DebugCylinderThink ( gentity_t* ent )
  465. {
  466.     vec3_t vec1;
  467.     vec3_t vec2;
  468.  
  469.     ent->nextthink = level.time + 1000;
  470.  
  471.     VectorCopy ( ent->parent->client->ps.origin, vec1 );
  472.     VectorCopy ( ent->r.currentOrigin, vec2 );
  473.     
  474.     vec1[2] = 0;
  475.     vec2[2] = 0;
  476.  
  477.     // IF we are too far away then kill it 
  478.     if ( Distance ( vec1, vec2 ) > ent->speed )
  479.     {
  480.         trap_UnlinkEntity ( ent );
  481.         return;
  482.     }
  483.  
  484.     trap_LinkEntity ( ent );
  485. }
  486.  
  487. /*
  488. =================================================================================
  489. G_SpawnDebugCylinder
  490. =================================================================================
  491. */
  492. void G_SpawnDebugCylinder ( vec3_t origin, float radius, gentity_t* clientent, float viewRadius, int colorIndex )
  493. {
  494.     gentity_t* ent;
  495.  
  496.     if ( !g_cheats.integer )
  497.     {
  498.         return;
  499.     }
  500.  
  501.     ent = G_Spawn ( );
  502.     ent->s.eType = ET_DEBUG_CYLINDER;
  503.     ent->s.time = colorIndex;
  504.     ent->s.time2 = (int) radius;
  505.     ent->parent = clientent;
  506.     ent->speed = viewRadius;
  507.  
  508.     VectorCopy ( origin, ent->s.origin );
  509.     VectorCopy ( origin, ent->r.currentOrigin );
  510.  
  511.     ent->nextthink = level.time + 1000;
  512.     ent->think = G_DebugCylinderThink;
  513.     
  514.     trap_LinkEntity ( ent );
  515. }
  516.  
  517.  
  518. void fx_think( gentity_t *ent ) 
  519. {
  520.     int        time;
  521.  
  522.     // play fx
  523.     G_PlayEffect( ent->health, ent->s.origin, ent->pos1 );
  524.  
  525.     if( ent->count >= 0 )    // stops it from rolling over, yeah kinda lame...
  526.     {
  527.         ent->count--;
  528.     }
  529.  
  530.     if( !ent->count )    // effect is suppose to play mCount times then dissapear
  531.     {
  532.         G_FreeEntity(ent);
  533.         return;
  534.     }
  535.  
  536.     // calc next play time
  537.     time = (ent->wait + flrand(0.0f, ent->random)) * 1000;    // need it in milliseconds 
  538.  
  539.     ent->think = fx_think;
  540.     ent->nextthink = level.time + time;
  541. }
  542.  
  543.  
  544. /*QUAKED fx_play_effect (.2 .5 .8) (-8 -8 -8) (8 8 8) START_OFF
  545. Plays specified effect file
  546.  
  547. "effect"    name of .efx file
  548. "wait"      seconds between triggerings, default 0.3
  549. "random"    wait variance in seconds, default 0
  550. "target"    direction of effect, default up
  551. "count"     plays effect this many times then deletes itself, default -1 = infinite 
  552.  
  553.  
  554. START_OFF    fx starts off
  555.  
  556.  
  557. */
  558.  
  559. void SP_fx_play_effect(gentity_t *ent)
  560. {
  561.     gentity_t    *target;
  562.     char        *fxName;
  563.  
  564.     G_SetOrigin( ent, ent->s.origin );
  565.  
  566.     G_SpawnString("effect", "", &fxName);
  567.     ent->health = G_EffectIndex(fxName);
  568.  
  569.     if (ent->wait == 0.0)
  570.     {
  571.         ent->wait = 0.3;
  572.     }
  573.  
  574.     target = G_Find(0, FOFS(targetname), ent->target);
  575.     if (target)
  576.     {
  577.         VectorSubtract( target->s.origin, ent->s.origin, ent->pos1 );
  578.         VectorNormalize( ent->pos1 );
  579.         // find angles
  580.         vectoangles( ent->pos1, ent->r.currentAngles );
  581.         // copy over to other angles
  582.         VectorCopy( ent->r.currentAngles, ent->s.angles );    
  583.         VectorCopy( ent->r.currentAngles, ent->s.apos.trBase );
  584.     }
  585.     else
  586.     {
  587.         ent->pos1[0] = ent->pos1[1] = 0.0;
  588.         ent->pos1[2] = 1.0;
  589.     }
  590.  
  591.     ent->think = fx_think;
  592.     ent->nextthink = level.time + 100;
  593. }
  594.  
  595.  
  596.